package com.qqt.csr.archive.assembler;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.qqt.csr.archive.entity.reader.ArtificialMessage;
import com.qqt.csr.archive.entity.reader.CsrImAccount;
import com.qqt.csr.archive.entity.reader.SmartMessage;
import com.qqt.csr.archive.entity.writer.ArchiveAccount;
import com.qqt.csr.archive.entity.writer.ArchiveConversation;
import com.qqt.csr.archive.entity.writer.ArchiveMessage;
import com.qqt.csr.archive.entity.writer.content.FileElemContent;
import com.qqt.csr.archive.entity.writer.content.ImageElemContent;
import com.qqt.csr.archive.entity.writer.content.TextElemContent;
import com.qqt.csr.archive.enums.*;
import com.qqt.csr.archive.response.ArchiveMessageResponse;
import com.qqt.csr.common.enums.DeletedEnum;
import java.util.*;
import java.util.stream.Collectors;

import static cn.hutool.core.date.DatePattern.NORM_DATETIME_FORMAT;

/**
 * @Author: yang hao
 * @Date: 2024/11/21 10:22
 * @Description: 归档消息 装配器
 **/
public class MessageArchiveAssembler {

    /**
     * 智能客服侧消息角色
     */
    private static final String ROLE_VISITOR = "1";
    private static final String ROLE_ROBOT = "2";
    private static final String ROLE_SYSTEM = "3";

    /**
     * 将人工客服消息转换为归档消息
     * @param artificialMessages {@link List<ArtificialMessage>} 人工客服消息集
     * @return {@link List<ArchiveMessage>} 归档消息集
     */
    public static List<ArchiveMessage> convertArchiveMessages(List<ArtificialMessage> artificialMessages) {
        if (artificialMessages == null || artificialMessages.isEmpty()) {
            return Collections.emptyList();
        }
        return artificialMessages.stream()
                .map(MessageArchiveAssembler::convertArchiveMessages)
                .collect(Collectors.toList());
    }

    /**
     * 将智能客服消息转换为归档消息
     * @param conversation {@link ArchiveConversation} 归档会话
     * @param smartMessages {@link List<ArchiveMessage>} 智能客服消息集
     * @return {@link List<ArchiveMessage>} 归档消息集
     */
    public static List<ArchiveMessage> convertSmartMessages(ArchiveConversation conversation, List<SmartMessage> smartMessages) {
        if (smartMessages == null || smartMessages.isEmpty()) {
            return Collections.emptyList();
        }
        return smartMessages.stream()
                .map(message -> convertSmartMessages(conversation, message))
                .collect(Collectors.toList());
    }

    /**
     * 将人工客服消息转换为归档消息
     * @param artificialMessage {@link ArtificialMessage} 人工客服消息
     * @return {@link ArchiveMessage} 归档消息
     */
    public static ArchiveMessage convertArchiveMessages(ArtificialMessage artificialMessage) {
        // 构建发送方和接收方
        ArchiveAccount sender = Optional.ofNullable(artificialMessage.getSender())
                .map(s -> ArchiveAccount.builder().id(s).build())
                .orElse(null);
        ArchiveAccount recipient = Optional.ofNullable(artificialMessage.getRecipient())
                .map(r -> ArchiveAccount.builder().id(r).build())
                .orElse(null);
        // 构建归档消息
        return ArchiveMessage.builder()
                .id(artificialMessage.getId())
                .seq(artificialMessage.getSeq())
                .sender(sender)
                .recipient(recipient)
                .conversationId(artificialMessage.getConversationId())
                .content(artificialMessage.getContent())
                .type(artificialMessage.getType())
                .flow(artificialMessage.getFlow())
                .artificialExt(artificialMessage.getArtificialExt())
                .deleted(artificialMessage.getDeleted())
                .createTime(artificialMessage.getCreateTime())
                .updateTime(artificialMessage.getUpdateTime())
                .roomId(artificialMessage.getRoomId())
                .sensitiveWords(artificialMessage.getSensitiveWords())
                .build();
    }

    /**
     * 将智能客服消息转换为归档消息
     * @param conversation {@link ArchiveConversation} 会话
     * @param smartMessage {@link SmartMessage} 智能客服消息
     * @return {@link ArchiveMessage} 归档消息
     */
    public static ArchiveMessage convertSmartMessages(ArchiveConversation conversation,SmartMessage smartMessage) {
        // 构建扩展信息
        String msgSendTime = DateUtil.format(DateUtil.parse(smartMessage.getMsgSendTime()), NORM_DATETIME_FORMAT);
        String createTime = DateUtil.format(DateUtil.parse(smartMessage.getCreateTime()), NORM_DATETIME_FORMAT);
        Map<String, Object> ext = Maps.newHashMap();
        ext.put("role", smartMessage.getRole());
        ext.put("isUpOrDownVote", smartMessage.getIsUpOrDownVote());
        ext.put("isComment", smartMessage.getIsComment());
        ext.put("isTriggerSensitive", smartMessage.getIsTriggerSensitive());
        ext.put("msgSendTime", msgSendTime);
        ext.put("associatePromptList", smartMessage.getAssociatePromptList());
        ext.put("relevance", smartMessage.getRelevance());
        ext.put("sourceType", smartMessage.getSourceType());
        ext.put("workFlowParams", smartMessage.getWorkFlowParams());
        // 构建归档消息
        Object content = formatMessage(smartMessage.getMessageType(), smartMessage.getMessage());
        ArchiveMessage message = ArchiveMessage.builder()
                .id(smartMessage.getId())
                .seq(smartMessage.getSeqTimeStamp() == null ? smartMessage.getId() : smartMessage.getSeqTimeStamp())
                .conversationId(smartMessage.getSessionId())
                .content(content)
                .flow(FlowType.IN)
                .type(MessageType.matchIgnoreCase(smartMessage.getMessageType()))
                .smartExt(JSONUtil.toJsonStr(ext))
                .deleted(DeletedEnum.NOT_DELETED)
                .createTime(createTime)
                .updateTime(msgSendTime)
                .build();
        // 填充发送方和接收方
        String role = smartMessage.getRole();
        if (StrUtil.isNotBlank(role)) {
            switch (role) {
                case ROLE_VISITOR -> fillVisitor(conversation, message, smartMessage);
                case ROLE_ROBOT -> fillRobot(conversation, message, smartMessage);
                case ROLE_SYSTEM -> fillSystem(conversation, message, smartMessage);
            }
        }
        return message;
    }

    /**
     * 填充访客和客服账号信息
     * @param archiveMessages {@link List<ArchiveMessage>} 归档消息集
     * @param userAccount {@link CsrImAccount} 访客账号
     * @param csAccount {@link CsrImAccount} 客服账号
     * @param conversationType {@link ConversationType} 会话类型
     */
    public static void fill(List<ArchiveMessage> archiveMessages, CsrImAccount userAccount, CsrImAccount csAccount, ConversationType conversationType) {
        if (archiveMessages == null || archiveMessages.isEmpty()) {
            return;
        }
        archiveMessages.forEach(archiveMessage -> fill(archiveMessage, userAccount, csAccount, conversationType));
    }

    /**
     * 填充访客和客服账号信息
     * @param archiveMessage {@link ArchiveMessage} 归档消息
     * @param userAccount {@link CsrImAccount} 访客账号
     * @param csAccount {@link CsrImAccount} 客服账号
     * @param conversationType {@link ConversationType} 会话类型
     */
    public static void fill(ArchiveMessage archiveMessage, CsrImAccount userAccount, CsrImAccount csAccount, ConversationType conversationType) {
        AccountType csOrRobot = conversationType.equals(ConversationType.SMART) ? AccountType.ROBOT : AccountType.CUSTOMER_SERVICE;
        if (!MessageType.SystemElem.equals(archiveMessage.getType())) {
            ArchiveAccount sender = archiveMessage.getSender();
            // 确保sender不为空
            Optional.ofNullable(sender).orElseThrow(() -> new IllegalArgumentException("sender不能为空, archiveMessage:" + JSONUtil.toJsonStr(archiveMessage)));

            if (userAccount.getId().toString().equals(sender.getId())) {
                // 填充访客信息
                archiveMessage.setSender(convert(sender, userAccount, AccountType.VISITOR, conversationType));
            }
            if (csAccount.getId().toString().equals(sender.getId())) {
                // 填充客服信息
                archiveMessage.setSender(convert(sender, csAccount, csOrRobot, conversationType));
            }
        }
        if (archiveMessage.getRecipient() != null) {
            ArchiveAccount recipient = archiveMessage.getRecipient();
            if (userAccount.getId().toString().equals(recipient.getId())) {
                // 填充访客信息
                archiveMessage.setRecipient(convert(recipient, userAccount, AccountType.VISITOR, conversationType));
            }
            if (csAccount.getId().toString().equals(recipient.getId())) {
                // 填充客服信息
                archiveMessage.setRecipient(convert(recipient, csAccount, csOrRobot, conversationType));
            }
        }
    }

    /**
     * 将账户转换为账户
     * @param imAccount {@link CsrImAccount} 账户
     * @param accountType {@link AccountType} 账户类型
     * @param conversationType {@link ConversationType} 会话类型
     * @return {@link ArchiveAccount} 账户
     */
    public static ArchiveAccount convert(ArchiveAccount account, CsrImAccount imAccount, AccountType accountType, ConversationType conversationType) {
        if (account.getAccountUserId() == null) {
            account.setAccountUserId(imAccount.getAccountUserId());
        }
        if (account.getAccountName() == null) {
            account.setAccountName(imAccount.getAccountName());
        }
        account.setType(accountType);
        if (conversationType.equals(ConversationType.ARTIFICIAL)) {
            account.setArtificialExt(imAccount.getExtJson());
        }
        if (conversationType.equals(ConversationType.SMART)) {
            account.setSmartExt(imAccount.getExtJson());
        }
        return account;
    }

    /**
     * 转换为归档消息响应集合
     * @param messages {@link ArchiveMessage} 归档消息集合
     * @return {@link List<ArchiveMessageResponse>} 归档消息响应集合
     */
    public static List<ArchiveMessageResponse> convert(List<ArchiveMessage> messages) {
        if (messages == null || messages.isEmpty()) {
            return Collections.emptyList();
        }
        return messages.stream()
                .map(MessageArchiveAssembler::convert)
                .collect(Collectors.toList());
    }

    /**
     * 转换为归档消息响应
     * @param message {@link ArchiveMessage} 归档消息集合
     * @return {@link ArchiveMessageResponse} 归档消息响应
     */
    public static ArchiveMessageResponse convert(ArchiveMessage message) {
        ArchiveMessageResponse response = BeanUtil.toBean(message, ArchiveMessageResponse.class);
        JSONObject objJson = JSONUtil.parseObj(message.getContent());
        objJson.remove("_class");
        response.setContent(JSONUtil.toBean(objJson, Object.class));
        return response;
    }

    /**
     * 填充访客（发送方）信息
     * @param conversation {@link ArchiveConversation} 归档会话
     * @param message {@link ArchiveMessage} 归档消息
     * @param smartMessage {@link SmartMessage} 智能客服消息
     */
    private static void fillVisitor(ArchiveConversation conversation, ArchiveMessage message, SmartMessage smartMessage) {
        // 访客 发送方 仅保存账户id与昵称、头像
        ArchiveAccount sender = ArchiveAccount.builder()
                .id(conversation.getUserAccountId())
                .accountName(smartMessage.getNickName())
                .headImg(smartMessage.getVisitorUrl())
                .build();
        // 机器人 接收方 无机器人信息，从会话中获取id存放
        ArchiveAccount recipient = ArchiveAccount.builder()
                .id(conversation.getCsAccountId())
                .accountName(smartMessage.getRobotName())
                .headImg(smartMessage.getRobotHeadUrl())
                .build();
        // 填充访客信息
        message.setSender(sender);
        message.setRecipient(recipient);
    }

    /**
     * 填充机器人（发送方）信息
     * @param conversation {@link ArchiveConversation} 归档会话
     * @param message {@link ArchiveMessage} 归档消息
     * @param smartMessage {@link SmartMessage} 智能客服消息
     */
    private static void fillRobot(ArchiveConversation conversation, ArchiveMessage message, SmartMessage smartMessage) {
        // 机器人 发送方 仅保存账户id与昵称、头像
        ArchiveAccount sender = ArchiveAccount.builder()
                .id(conversation.getCsAccountId())
                .accountName(smartMessage.getRobotName())
                .headImg(smartMessage.getRobotHeadUrl())
                .build();
        // 访客 接收方 仅保存账户id与昵称、头像
        ArchiveAccount recipient = ArchiveAccount.builder()
                .id(conversation.getUserAccountId())
                .accountName(smartMessage.getNickName())
                .headImg(smartMessage.getVisitorUrl())
                .build();
        // 填充访客信息
        message.setSender(sender);
        message.setRecipient(recipient);
    }

    /**
     * 填充无（发送方）信息
     * @param conversation {@link ArchiveConversation} 归档会话
     * @param message {@link ArchiveMessage} 归档消息
     * @param smartMessage {@link SmartMessage} 智能客服消息
     */
    private static void fillSystem(ArchiveConversation conversation, ArchiveMessage message, SmartMessage smartMessage) {
        // 发送方为空
        // 访客 接收方 仅保存账户id与昵称、头像
        ArchiveAccount recipient = ArchiveAccount.builder()
                .id(conversation.getUserAccountId())
                .accountName(smartMessage.getNickName())
                .headImg(smartMessage.getVisitorUrl())
                .build();
        // 填充访客信息
        message.setSender(null);
        message.setRecipient(recipient);
    }

    /**
     * 格式化消息 智能客服
     * @param messageType {@link String} 消息类型
     * @param message {@link String} 消息内容
     * @return {@link Object} 格式化后的消息
     */
    private static Object formatMessage(String messageType, String message) {
        return switch (MessageType.matchIgnoreCase(messageType)) {
            case TextElem, RichElem, MarkdownElem, SystemElem, WorkFlowElem -> formatTextElem(message);
            case ImageElem -> formatImageElem(message);
            case FileElem -> formatFileElem(message);
        };
    }

    /**
     * 格式化消息 文本消息
     * @param message {@link String} 消息内容
     * @return {@link TextElemContent} 格式化后的消息
     */
    private static TextElemContent formatTextElem(String message) {
        return TextElemContent.builder().text(message).build();
    }

    /**
     * 格式化消息 图片消息
     * @param message {@link String} 消息内容
     * @return {@link ImageElemContent} 格式化后的消息
     */
    private static ImageElemContent formatImageElem(String message) {
        ImageElemContent.ImageInfo info = ImageElemContent.ImageInfo.builder()
                .type(ImageType.ARTWORK)
                .url(message)
                .build();
        List<ImageElemContent.ImageInfo> infos = Lists.newArrayList(info);
        return ImageElemContent.builder()
                .imageInfoArray(infos)
                .build();
    }

    /**
     * 格式化消息 文件消息
     * @param message {@link String} 消息内容
     * @return {@link FileElemContent} 格式化后的消息
     */
    private static FileElemContent formatFileElem(String message) {
        return FileElemContent.builder().url(message).build();
    }

}
